#pragma once
#include <iostream>
#include <list>
#include <unordered_set>
#include <functional>
#include <memory>
#include <unordered_map>
#include <cassert>
#include <unistd.h>
#include <sys/timerfd.h>
#include "chennel.hpp"

#define DEFAULT_TIMEOUT 30
using OnTimerCallback = std::function<void()>;
using ReleaseCallback = std::function<void()>;
class Timer {
    private:
        using ReleaseCallback = std::function<void()>;
        uint64_t _timer_id;
        OnTimerCallback _timer_callback;
        ReleaseCallback _release_callback;
    public:
        Timer(uint64_t timer_id): _timer_id(timer_id){}
        ~Timer(){ 
            /*执行定时任务*/
            _timer_callback(); 
            /*由timequeue设置的释放回调，主要是移除timequeue中保存的Timer信息*/
            _release_callback(); 
        }
        uint64_t id() { return _timer_id; }
        /*这个是设置当前的定时任务到期时要执行的任务函数*/
        void set_on_time_callback(const OnTimerCallback &cb) {_timer_callback = cb; }
        /*这个是当前的定时任务到期时，从timer_queue的hash表中移除任务信息*/
        void set_release_callback(const ReleaseCallback &cb) {_release_callback = cb; }
};

class TimerQueue {
    public:
        using WeakTimer = std::weak_ptr<Timer>;
        using PtrTimer = std::shared_ptr<Timer>;
        using Bucket = std::unordered_set<PtrTimer>;
        using BucketList = std::list<Bucket>;
        TimerQueue::TimerQueue(EventLoop *loop):
            _loop(loop), 
            _timer_fd(TimerQueue::create_timerfd()),
            _channel(new Channel(loop, _timer_fd)), 
            _capacity(DEFAULT_TIMEOUT), 
            _conns(DEFAULT_TIMEOUT){
            /*设置每次定时器时间到了的回调*/
            _channel->set_read_callback(std::bind(&TimerQueue::on_time, this));
            /*在eventloop线程中，将当前定时器关联_channel添加的可读事件监控中*/
            _channel->enable_read();
        }
        void TimerQueue::on_time() {
            read_timerfd();
            if (_conns.size() == _capacity) {
                _conns.pop_front();
            }
            _conns.push_back(Bucket());
        }
        void TimerQueue::erase(uint64_t id) {
            auto it = _timers.find(id);
            if (it != _timers.end()) {
                _timers.erase(it);
            }
        }
        void TimerQueue::timer_add(const OnTimerCallback &cb, uint64_t id) {
            Timer *timer = new Timer(id);
            timer->set_on_time_callback(cb);
            timer->set_release_callback(std::bind(&TimerQueue::erase, this, id));
            PtrTimer pt(timer);
            _timers[id] = WeakTimer(pt);
            _conns.back().insert(pt);
        }
        void TimerQueue::timer_refresh(uint64_t id) {
            auto it = _timers.find(id);
            /*不可能存在这种情况呀, 添加的定时回调找不着*/
            assert (it != _timers.end());
            _conns.back().insert(PtrTimer(it->second));
        }
    private:
        static int TimerQueue::create_timerfd() {
            /*这里其实就是创建了一个每秒中会超时一次的定时器*/
            int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
            struct itimerspec itm;
            itm.it_value.tv_sec = 1;//设置第一次超时的时间
            itm.it_value.tv_nsec = 0;
            itm.it_interval.tv_sec = 1;//第一次超时后，每隔多长时间超时
            itm.it_interval.tv_nsec = 0;
            timerfd_settime(timerfd, 0, &itm, NULL);//启动定时器
            return timerfd;
        }
        void TimerQueue::read_timerfd() {
            /*每次定时器时间到了，都会由系统向timerfd写入8字节数据，这个数据虽然当前没 用，但是必须取出来，不然会持续触发epoll就绪事件*/
            uint64_t times;
            int ret = ::read(_timer_fd, (char*)&times, sizeof(times));
            assert(ret == sizeof(times));
        }
    private:
        EventLoop *_loop;
        int _timer_fd;
        std::unique_ptr<Channel> _channel;

        int _capacity;
        std::unordered_map<uint64_t, WeakTimer> _timers;
        BucketList _conns;
};